/**
 * PESA2MNO.java
 * @author Juan J. Durillo
 * @version 1.0
 * 
 */
package ufpr.mestrado.ais.metaheuristics.pesa2mno;

import jmetal.base.Algorithm;
import jmetal.base.Operator;
import jmetal.base.Problem;
import jmetal.base.SolutionSet;
import jmetal.util.JMException;
import ufpr.mestrado.ais.base.SolutionMNO;
import ufpr.mestrado.ais.base.operator.selection.PESA2SelectionMNO;
import ufpr.mestrado.ais.util.AdaptiveGridArchiveMNO;

/**
 * This class implements the PESA2MNO algorithm.
 */
public class PESA2MNO extends Algorithm {

	/**
	 * 
	 */
	private static final long serialVersionUID = -1313961517512103358L;
	/**
	 * Stores the problem to solve
	 */
	private Problem problem_;

	/**
	 * Constructor Creates a new instance of PESA2MNO
	 */
	public PESA2MNO(Problem problem) {
		problem_ = problem;
	} // PESA2MNO

	/**
	 * Runs of the PESA2MNO algorithm.
	 * 
	 * @return a <code>SolutionSet</code> that is a set of non dominated
	 *         solutions as a result of the algorithm execution
	 * @throws JMException
	 */
	public SolutionSet execute() throws JMException, ClassNotFoundException {

		int archiveSize, bisections, maxEvaluations, evaluations, populationSize;

		SolutionSet solutionSet;

		Operator crossover, mutation, selection;

		// Read parameters
		populationSize = ((Integer) (inputParameters_.get("populationSize")))
				.intValue();

		archiveSize = ((Integer) (inputParameters_.get("archiveSize")))
				.intValue();

		bisections = ((Integer) (inputParameters_.get("bisections")))
				.intValue();

		maxEvaluations = ((Integer) (inputParameters_.get("maxEvaluations")))
				.intValue();

		// Get the operators
		crossover = operators_.get("crossover");

		mutation = operators_.get("mutation");

		// Initialize the variables
		evaluations = 0;

		final AdaptiveGridArchiveMNO archive = new AdaptiveGridArchiveMNO(
				archiveSize, bisections, problem_.getNumberOfObjectives());

		solutionSet = new SolutionSet(populationSize);

		selection = new PESA2SelectionMNO();

		// -> Create the initial individual and evaluate it and his constraints
		for (int i = 0; i < populationSize; i++) {

			SolutionMNO solution = new SolutionMNO(problem_);
			// Solution solution = new Solution(problem_);

			problem_.evaluate(solution);

			problem_.evaluateConstraints(solution);

			// evaluations++;

			solutionSet.add(solution);
		}
		// <-

		// Incorporate non-dominated solution to the archive
		for (int i = 0; i < solutionSet.size(); i++) {

			// Only non dominated are accepted by the archive
			archive.add(solutionSet.get(i));
		}

		// Clear the init solutionSet
		solutionSet.clear();

		// Iterations....
		SolutionMNO[] parents = new SolutionMNO[2];

		do {
			// -> Create the offSpring solutionSet
			while (solutionSet.size() < populationSize) {

				parents[0] = (SolutionMNO) selection.execute(archive);

				parents[1] = (SolutionMNO) selection.execute(archive);

				SolutionMNO[] offSpring = (SolutionMNO[]) crossover
						.execute(parents);

				mutation.execute(offSpring[0]);

				problem_.evaluate(offSpring[0]);

				problem_.evaluateConstraints(offSpring[0]);

				// evaluations++;

				solutionSet.add(offSpring[0]);
			}

			for (int i = 0; i < solutionSet.size(); i++)
				archive.add(solutionSet.get(i));

			// Clear the solutionSet
			solutionSet.clear();

			evaluations++;

		} while (evaluations < maxEvaluations);

		// Return the solutionSet of non-dominated individual
		return archive;
	} // execute
} // PESA2MNO
